package com.lightsaber.trade.cloth.web.category;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.commons.lang.StringUtils;
import org.apache.struts2.convention.annotation.Action;
import org.apache.struts2.convention.annotation.Namespace;
import org.apache.struts2.convention.annotation.Result;
import org.apache.struts2.convention.annotation.Results;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springside.modules.utils.web.struts2.Struts2Utils;

import com.lightsaber.trade.core.web.BaseAction;
import com.lightsaber.trade.cloth.entity.category.Category;
import com.lightsaber.trade.cloth.entity.category.CategoryBranch;
import com.lightsaber.trade.cloth.entity.category.CategoryNode;
import com.lightsaber.trade.cloth.entity.category.CategoryNodeType;
import com.lightsaber.trade.cloth.entity.category.CategoryOwner;
import com.lightsaber.trade.cloth.entity.category.InputType;
import com.lightsaber.trade.cloth.entity.category.SourceType;
import com.lightsaber.trade.cloth.service.category.CategoryNodeService;
import com.lightsaber.trade.cloth.service.category.CategoryOwnerService;
import com.lightsaber.trade.cloth.service.category.CategoryPlannerService;
import com.lightsaber.trade.cloth.service.category.CategoryService;
import com.lightsaber.trade.cloth.service.param.ParamService;

@Namespace("/category")
@Action(value = "categoryBranch")
@Results({ @Result(name = "create-edit-category-node", location = "create-edit-category-node.jsp"),
        @Result(name = "move-to-tree", location = "move-to-tree.jsp") })
public class CategoryBranchAction extends BaseAction {

    private static final long serialVersionUID = -6133932528005700711L;
    private static final Logger log = LoggerFactory.getLogger(CategoryBranchAction.class);
    @Autowired
    private transient CategoryNodeService categoryNodeService;
    @Autowired
    private transient CategoryService categoryService;
    @Autowired
    private transient ParamService paramService;
    @Autowired
    private transient CategoryPlannerService plannerService;
    @Autowired
    private transient CategoryOwnerService ownerService;

    private CategoryBranch categoryNode;
    private String parentId;
    private String categoryId;
    private String categoryNodeId;
    private String categoryNodeType;
    private String parentNodeType;
    private String treeType;
    private boolean hasOwners;

    private Map<String, String> inputTypeMap;
    private Map<String, String> sourceTypeMap;

    @Override
    public String execute() {
        return list();
    }

    public String list() {

        categoryNode = categoryNodeService.findBranchById(categoryNodeId);
        List<CategoryOwner> list = ownerService.findByCategoryNodeId(categoryNodeId);
        // if (categoryNode.getCategoryOwners() == null
        // || categoryNode.getCategoryOwners().size() == 0) {
        if (list.isEmpty()) {
            setHasOwners(false);
        } else {
            setHasOwners(true);
        }
        CategoryNode parentNode = categoryNode.getParent();
        if (parentNode == null) {
            setParentId(null);
            setParentNodeType("Root");
            setCategoryNodeType(CategoryNodeType.Root.name());
        } else {
            setParentId(parentNode.getId());
            setParentNodeType("Branch");
            setCategoryNodeType(CategoryNodeType.Branch.name());
        }
        setCategoryNodeId(categoryNodeId);

        setCategoryId(categoryId);
        Category category = categoryService.get(categoryId);
        if (StringUtils.isBlank(category.getBranchName())) {
            setTreeType("Root");
        } else {
            setTreeType("Branch");
        }

        setInputTypeMap(InputType.list());
        setSourceTypeMap(SourceType.list());
        return "create-edit-category-node";
    }

    public String createBranch() throws Exception {
        setParentId(categoryNodeId);
        setCategoryId(categoryId);
        setCategoryNodeId("");
        categoryNode = null;
        setCategoryNodeType(CategoryNodeType.Branch.name());
        setTreeType(treeType);
        setInputTypeMap(InputType.list());
        setSourceTypeMap(SourceType.list());
        return "create-edit-category-node";
    }

    @Override
    public String input() throws Exception {
        return null;
    }

    public String save() throws Exception {
        try {
            CategoryNode parent = categoryNodeService.findById(parentId);
            categoryNode.setParent(parent);

            categoryNodeService.saveBranch(categoryNode);

            if (StringUtils.isBlank(categoryNodeId)) {
                plannerService.inheritPlanners(categoryNode);
            }
            categoryNodeId = categoryNode.getId();
            setCategoryNodeId(categoryNode.getId());

            addActionMessage(getText(PROCESSED_SUCCESS));

            return list();
        } catch (Exception e) {
            addActionError(e.getMessage());
            if (StringUtils.isBlank(categoryNodeId)) {
                return createBranch();
            } else {
                return list();
            }
        }

    }

    public void changeParent() {
        try {
            categoryNodeService.changeParentNode(categoryNodeId, parentId);
            Struts2Utils.renderText("success");
        } catch (Exception e) {
            log.error("delete leaf error : {}", e.getMessage());
            Struts2Utils.renderText(e.getMessage());
        }
    }

    public String goToMoveToPage() {
        setCategoryId(categoryId);
        setCategoryNodeId(categoryNodeId);
        setCategoryNodeType(categoryNodeType);
        return "move-to-tree";
    }

    public void deleteBranch() {
        try {
            categoryNodeService.deleteById(categoryNodeId);
            Struts2Utils.renderText("success");
        } catch (Exception e) {
            addActionError(e.getMessage());
            log.error("delete leaf error : {}", e.getMessage());
            Struts2Utils.renderText(e.getMessage());
        }
    }

    public void inheritParentNode() {
        CategoryNode parentNode = categoryNodeService.findById(parentId);
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("inputType", parentNode.getInputType().name());
        map.put("sourceType", parentNode.getSourceType().name());
        Struts2Utils.renderJson(map);
    }

    public void ajaxValidateNodeName() {
        try {
            CategoryNode node = new CategoryNode();
            node.setName(categoryNode.getName());
            node.setId(categoryNode.getId());
            CategoryNode parentNode = categoryNodeService.findById(parentId);
            node.setParent(parentNode);
            log.info("ajaxValidateNodeName", categoryNode.getName());
            categoryNodeService.validateCategoryNode(node);
            Struts2Utils.renderText("success");
        } catch (Exception e) {
            log.error("ajaxValidateNodeName error : {}", e);
            Struts2Utils.renderText(e.getMessage());
        }
    }

    public void ajaxCheckDisciplineView() {
        try {
            CategoryNode parent = categoryNodeService.findById(parentId);
            boolean isView = checkParentHasDiscipline(parent);
            Struts2Utils.renderText("" + isView);
        } catch (Exception e) {
            log.error("ajaxValidateNodeName error : {}", e.getMessage());
            Struts2Utils.renderText(e.getMessage());
        }
    }

    private boolean checkParentHasDiscipline(final CategoryNode parent) {
        // CategoryNode parent = currentNode.getParent();
        if (parent == null) {
            return false;
        }
        if (parent.getIsDisciplineView() == 1) {
            return true;
        } else {
            return checkParentHasDiscipline(parent.getParent());
        }
    }

    public String getCategoryNodeType() {
        return categoryNodeType;
    }

    public void setCategoryNodeType(final String categoryNodeType) {
        this.categoryNodeType = categoryNodeType;
    }

    public CategoryBranch getCategoryNode() {
        return categoryNode;
    }

    public void setCategoryNode(final CategoryBranch categoryNode) {
        this.categoryNode = categoryNode;
    }

    public String getParentId() {
        return parentId;
    }

    public void setParentId(final String parentId) {
        this.parentId = parentId;
    }

    public String getCategoryNodeId() {
        return categoryNodeId;
    }

    public void setCategoryNodeId(final String categoryNodeId) {
        this.categoryNodeId = categoryNodeId;
    }

    public String getCategoryId() {
        return categoryId;
    }

    public void setCategoryId(final String categoryId) {
        this.categoryId = categoryId;
    }

    public String getParentNodeType() {
        return parentNodeType;
    }

    public void setParentNodeType(final String parentNodeType) {
        this.parentNodeType = parentNodeType;
    }

    public String getTreeType() {
        return treeType;
    }

    public void setTreeType(final String treeType) {
        this.treeType = treeType;
    }

    public boolean isHasOwners() {
        return hasOwners;
    }

    public void setHasOwners(final boolean hasOwners) {
        this.hasOwners = hasOwners;
    }

    public Map<String, String> getInputTypeMap() {
        return inputTypeMap;
    }

    public void setInputTypeMap(final Map<String, String> inputTypeMap) {
        this.inputTypeMap = inputTypeMap;
    }

    public Map<String, String> getSourceTypeMap() {
        return sourceTypeMap;
    }

    public void setSourceTypeMap(final Map<String, String> sourceTypeMap) {
        this.sourceTypeMap = sourceTypeMap;
    }

    public ParamService getParamService() {
        return paramService;
    }

    public void setParamService(final ParamService paramService) {
        this.paramService = paramService;
    }

}
